#pragma once

#include "sclippallette.h"
#include "sanimationviewer.h"
#include "framezoomview.h"
#include "dividedpanel.h"
#include "editorpanel.h"

class SpriteEditor : public EditorPanel
{
private:
	/** manages the current sprite frame for editing */
	FrameZoomViewPanel m_frameViewer;
	/** the sprite to draw/edit (allocated aggregate) */
	Sprite * m_sprite;
	/** where new clips are added to the current frame from */
	SClipPallette m_clipPallette;
	/** shows all sprite animations */
	SAnimationViewer m_animationViewer;
	/** divides the editor */
	DividedPanel m_frameClipDivider, m_topBottomDivider;
	/** whether or not to animate the sprite */
	bool m_isRunning;
public:
	Sprite * getSprite(){return m_sprite;}
	SClipPallette * getClipPallette(){
		//HACK: 
		//The this pointer should never be null; however, it is when
		//I run this program in debug and release mode. 
		///
		//Without this hack, it returns a bogus pointer
		//and bmpcliprect.draw() function tries to use the
		//bogus pointer resulting in a crash.
		///
		//With this hack, it returns null so that the
		//safegaurds within bmpcliprect.draw() function
		//to gaurd against using a null pointer work.
		//AVN
		if (this == 0) return 0;
		return &m_clipPallette;
	}
	SAnimationViewer * getAnimationViewer(){return &m_animationViewer;}
	bool isRunning(){return m_isRunning;}
	void setRunning(const bool & a_running){m_isRunning=a_running;}
	void release()
	{
		EditorPanel::release();
		if(m_sprite){delete m_sprite;m_sprite=0;}
	}
	FrameZoomViewPanel * getFrameViewer()
	{
		return &m_frameViewer;
	}
	bool update(const int & a_ms)
	{
		bool updated = false;
		if(isRunning())
		{
			int a = m_sprite->getAnimationIndex();
			int f = m_sprite->getFrameIndex();
			updated = m_sprite->update(a_ms);
			// if the sprite updated during the update, move it back
			if(updated)
			{
				m_frameViewer.changeFrame(a, f, 
					m_sprite->getAnimationIndex(), 
					m_sprite->getFrameIndex());
			}
			setDirty(0);
		}
		return updated;
	}
	SpriteEditor():EditorPanel(),m_sprite(0),m_isRunning(false)
	{
		setZoomViewPanel(&m_frameViewer);
		m_frameClipDivider.setSeperationHorizontal(true);
		m_frameClipDivider.addChild(&m_zoomViewParent);
		m_frameClipDivider.addChild(&m_clipPallette);
		int index = m_children.indexOf(&m_zoomViewParent);
		m_topBottomDivider.setSeperationHorizontal(false);
		m_topBottomDivider.addChild(&m_frameClipDivider);
		m_topBottomDivider.addChild(&m_animationViewer);
		setChild(index, &m_topBottomDivider);
		m_frameViewer.setClipPallette(&m_clipPallette);
		m_frameViewer.setAnimationViewer(&m_animationViewer);
	}

	bool loadMethod(const char * a_filename);
	bool saveMethod(const char * a_filename);

	void setArea(const SRect & area)
	{
		EditorPanel::setArea(area);
		SRect contentArea(area);
		contentArea.setMinY(m_toolbar.getArea()->getMaxY());
		m_topBottomDivider.setArea(contentArea);
		m_frameViewer.setZoom(4, SPoint());
	}

	void setSprite(Sprite * a_sprite)
	{
		if(m_sprite){m_sprite->release();delete m_sprite;m_sprite=0;}
		m_sprite = a_sprite;
		m_frameViewer.setSprite(a_sprite);
		m_clipPallette.addSpriteClips(a_sprite);
		m_animationViewer.set(a_sprite);
	}

	static void saveSpriteToBuffer(Sprite * s, TemplateVectorList<char> * a_buffer);

	/**
	 * @param a_spriteFile contents of the file as a character array
	 * @param a_out where to write the numeric data to
	 */
	void convertSpriteFileToNumberList(const char * a_spriteFile, TemplateVector<short> & a_out);

	char * loadNewSpriteFile(const char * a_filename);

	void initUI(Panel * a_parent)
	{
		setParent(a_parent);
		MasterPanel * mp = (MasterPanel *)getMasterPanel();
		// where in the tools.bmp image do icons for each tool exist? TODO move to a script?
		ToolBar::ToolData toolData[] = {
			{"Save", mp->getImageClip(4)},
			{"Load", mp->getImageClip(29)},
			{"AddAnimation", mp->getImageClip(13)},
			{"AddFrame", mp->getImageClip(12)},
			{"AddCopyFrame", mp->getImageClip(33)},
			{"AddClip", mp->getImageClip(16)},
			{"MoveClipUp", mp->getImageClip(15)},
			{"MoveClipDown", mp->getImageClip(14)},
			{"FlipClipX", mp->getImageClip(30)},
			{"FlipClipY", mp->getImageClip(31)},
			{"FlipClip90", mp->getImageClip(32)},
			{"PrevFrame", mp->getImageClip(7)},
			{"RunAnimation", mp->getImageClip(10)},
			{"NextFrame", mp->getImageClip(9)},
			{"DeleteClip", mp->getImageClip(11)},
			{"DeleteFrame", mp->getImageClip(19)},
			{"DeleteAnimation", mp->getImageClip(20)},
		};
		int numTools = sizeof(toolData)/sizeof(ToolBar::ToolData);
		EditorPanel::setTools(toolData, numTools);
	}
};